package io.renren.modules.project.service.impl;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpATTRS;
import io.renren.common.utils.RedisUtils;
import io.renren.common.utils.sftp.FileProgressMonitor;
import io.renren.common.utils.sftp.SFTPFactory;
import io.renren.common.utils.sftp.SFTPProperties;
import io.renren.common.utils.sftp.SFTPUtils;
import io.renren.common.websocket.SocketHeartbeat;
import io.renren.modules.project.dao.FileVoDao;
import io.renren.modules.project.service.FileVoService;
import io.renren.modules.project.vo.FileVoEntity;
import io.renren.modules.sys.entity.SysUserEntity;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Service("FileVoService")
public class FileVoServiceImpl extends ServiceImpl<FileVoDao, FileVoEntity>  implements FileVoService {

    @Value("${spring.file.uploadFolder}")
    private String uploadFolder;

    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static AtomicInteger onlineNum = new AtomicInteger(0);

    //concurrent包的线程安全Set，用来存放每个客户端对应的WebSocketServer对象。
    private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();

    @Autowired
    private SFTPProperties sftpProperties;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public List<FileVoEntity> getListByPath(Map<String, Object> params) throws Exception{
        try {
            List<FileVoEntity> fList = new ArrayList<>();
            ChannelSftp sftp = this.getSftpInstance();
            String curpath =  (String)params.get("curpath");
            // ftp判断路径是否存在
            if (!SFTPUtils.isDirExist(sftp , sftpProperties.getBasePath() +curpath)) {
                throw new Exception("异常，路径不存在！");
            }
            Vector v = sftp.ls(sftpProperties.getBasePath() + curpath);
            if (v.size() > 0) {
                // System.out.println("本次处理文件个数不为零,开始下载...fileSize=" + v.size());
                Iterator it = v.iterator();
                while (it.hasNext()) {
                    ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) it.next();
                    String filename = entry.getFilename();
                    SftpATTRS attrs = entry.getAttrs();
                    if(!filename.equals("..") && !filename.equals(".")) {
                        FileVoEntity fileVo = new FileVoEntity();
                        fileVo.setFileName(filename);
                        fileVo.setIsDir(attrs.isDir());
                        fileVo.setFileType(filename.lastIndexOf(".") == -1? ( attrs.isDir() ? "": "?" ):
                                filename.substring(filename.lastIndexOf(".")) );
                        fileVo.setFileSize(entry.getAttrs().getSize());
                        fileVo.setFilePath(curpath);
                        fList.add(fileVo);
                    }
                }
            }
//            // 判断根目录是否存在，不存在则创建
//            File dir = new File(uploadFolder);
//            if (!dir.exists()) {
//                dir.mkdir();
//            }
//
//            // 判断查找的目录是否存在
//            File curdir = new File(uploadFolder + curpath);
//            if (!curdir.exists()) {
//               throw new Exception("路径不存在！");
//            }
//

//            File[] files = curdir.listFiles();
//            if (files != null) {
//                for (File f : files) {
//                    FileVoEntity fileVo = new FileVoEntity();
//                    fileVo.setFileName(f.getName());
//                    fileVo.setIsDir(f.isDirectory());
//                    fileVo.setFileSize(f.isDirectory()? FileUtils.sizeOfDirectory(f):f.length());
//                    fileVo.setFileType(f.getName().lastIndexOf(".") == -1? ( f.isDirectory() ? "": "?" ):
//                            f.getName().substring(f.getName().lastIndexOf(".")) );
//                    fileVo.setFilePath(f.getParent().replace(uploadFolder.substring(0,uploadFolder.length()-1), ""));
//                    fList.add(fileVo);
//                }
//            }
            return fList;
        } catch (Exception ex) {
            throw ex;
        }

    }

    @Override
    public List<FileVoEntity> getListBySearchVal(Map<String, Object> params) throws Exception{
        ChannelSftp sftp = this.getSftpInstance();
        String searchVal = (String)params.get("searchValue");

        List<FileVoEntity> fList = new ArrayList<>();
        SFTPUtils.getFileListRecurse(sftp,sftpProperties.getBasePath() ,fList, searchVal.trim(),sftpProperties.getBasePath());
        return fList;
    }

    @Override
    public void sftpUploadFile(MultipartFile multiFile,String path) {


        try {
            SFTPFactory factory = new SFTPFactory();
            factory.connect(sftpProperties,redisUtils);
            ChannelSftp sftp = factory.getSftp();
//            if ((sftpProperties.getBasePath() + path).equals(sftp.getCwd()))
            // 获取当前用户Id
            Long createUserId =  ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUserId();

//            for (MultipartFile multiFile : multipartFiles) {
                // 获取文件名
                String fileName = multiFile.getOriginalFilename();
                // 获取文件后缀
                String prefix = fileName.substring(fileName.lastIndexOf("."));
                File dest = File.createTempFile(fileName, prefix);
                multiFile.transferTo(dest);
//            sftp.cd(sftpProperties.getBasePath() + path);
                FileProgressMonitor monitor = new FileProgressMonitor(multiFile.getOriginalFilename(),dest.length());
                new Thread(new SocketHeartbeat(createUserId,monitor)).start();

                sftp.put(new FileInputStream(dest), sftpProperties.getBasePath() + path + "/" +fileName,monitor);
                factory.disconnect();
//            }

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {

        }
//        FtpUtils ftp = this.initFtpServer();
//        try {
//            for (MultipartFile multiFile : multipartFiles) {
//                // 获取文件名
//                String fileName = multiFile.getOriginalFilename();
//                // 获取文件后缀
//                String prefix = fileName.substring(fileName.lastIndexOf("."));
//                File dest = File.createTempFile(fileName, prefix);
//                multiFile.transferTo(dest);
//                ftp.uploadFile(path,fileName,dest);
//            }
////            sftp.bacthUploadFile("/home/ubuntu/upload/cad/", "D:\\1002\\", false);
//        } catch (Exception e) {
//            // TODO: handle exception
//            e.printStackTrace();
//        } finally {
//            ftp.disconnect();
//        }
    }

    @Override
    public void sftpRename(FileVoEntity fileVoEntity) throws Exception{
        try {
            String path = fileVoEntity.getFilePath();
            String oldName = sftpProperties.getBasePath() + path + "/" + fileVoEntity.getOldName();
            String newName = sftpProperties.getBasePath() + path + "/" + fileVoEntity.getNewName();
            ChannelSftp sftp = this.getSftpInstance();
            // ftp判断路径是否存在
            if(fileVoEntity.getIsDir()) {
                if (!SFTPUtils.isDirExist(sftp , oldName)) {
                    throw new Exception("异常，路径不存在！");
                }
                if (SFTPUtils.isDirExist(sftp , newName)) {
                    throw new Exception("文件重复，请重新命名！");
                }
                sftp.rename(oldName, newName);
            } else {
                sftp.rename(oldName,newName);
//                InputStream fileStream = sftp.get(sftpProperties.getBasePath() + path + "/" + oldName);
//                sftp.put(fileStream, sftpProperties.getBasePath() + path + "/" + newName);
            }
        }catch (Exception ex){
            throw ex;
        }
    }

    @Override
    public void sftpDelFile(FileVoEntity fileVoEntity) throws Exception {
        try {
            ChannelSftp sftp = this.getSftpInstance();
            String pathFile = sftpProperties.getBasePath() + fileVoEntity.getFilePath() + "/" + fileVoEntity.getFileName();
            if (fileVoEntity.getIsDir()) {
                sftp.rmdir(pathFile);
            } else {
                sftp.rm(pathFile);
            }
        }catch (Exception ex) {
            throw ex;
        }
    }

    public ChannelSftp getSftpInstance() {
        return SFTPFactory.getInstance().makeConnection(sftpProperties,redisUtils);
    }

}
